package ru.spb.osll.myfit.wikiverifier.iterator;

import java.io.IOException;
import java.net.URLClassLoader;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import ru.spb.osll.myfit.common.Page;
import ru.spb.osll.myfit.common.Table;
import ru.spb.osll.myfit.server.MyFitClassLoaderFactory;
import ru.spb.osll.myfit.server.fixtureiterator.FileFactory;
import ru.spb.osll.myfit.server.handler.PageLoader;
import ru.spb.osll.myfit.server.parser.TableElementParser;
import ru.spb.osll.myfit.server.templateloader.JarTableTemplateLoader;
import ru.spb.osll.myfit.server.templateloader.TableTemplateLoader;
import ru.spb.osll.myfit.wikiverifier.WikiVerifier;
import ru.spb.osll.myfit.wikiverifier.result.AggregatedVerificationResult;
import ru.spb.osll.myfit.wikiverifier.result.PageVerificationResult;
import ru.spb.osll.myfit.wikiverifier.resulthandler.AggregatedVerificationResultHandler;
import ru.spb.osll.myfit.wikiverifier.resulthandler.PageVerificationResultHandler;

public class WikiVerifierFSIteratorListener implements
		FileSystemIteratorListener {
	private JarTableTemplateLoader m_templateLoader;
	private WikiVerifier m_verifier;
	private PageLoader m_pageLoader;
	private List<PageVerificationResultHandler> m_pageResultHandlers;
	private List<AggregatedVerificationResultHandler> m_aggregatedResultHandlers;
	private AggregatedVerificationResult m_aggregatedResult;
	private String m_verificatonPath;

	public WikiVerifierFSIteratorListener(String jarPath, String verificatonPath) {
		URLClassLoader classLoader = new MyFitClassLoaderFactory(new FileFactory())
		.createClassLoader(jarPath, jarPath);
		m_templateLoader = new JarTableTemplateLoader(jarPath, classLoader);
		m_verifier = new WikiVerifier(getTemplates(m_templateLoader),
				m_templateLoader.getFixtureClasses());
		m_verificatonPath = verificatonPath;
		m_pageLoader = new PageLoader(verificatonPath);
		m_pageResultHandlers = new LinkedList<PageVerificationResultHandler>();
		m_aggregatedResultHandlers = new LinkedList<AggregatedVerificationResultHandler>();
		m_aggregatedResult = new AggregatedVerificationResult();
		m_pageResultHandlers.add(m_aggregatedResult);
	}
	
	public void addResultHandler(PageVerificationResultHandler handler) {
		m_pageResultHandlers.add(handler);
	}
	
	public void addResultHandler(AggregatedVerificationResultHandler handler) {
		m_aggregatedResultHandlers.add(handler);
	}

	@Override
	public void listen(String fileName) {
		try {
			String pagePath = fileName.replaceAll("/", ".");
			pagePath = pagePath.replaceAll("\\", ".");
			Page page = m_pageLoader.loadPage(fileName, pagePath, null);
			PageVerificationResult result = m_verifier.verifyPage(page, true);
			handleResult(fileName, result);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void handleFinish() {
		for(AggregatedVerificationResultHandler handler : m_aggregatedResultHandlers) {
			handler.handleResult(m_verificatonPath, m_aggregatedResult);
		}
	}

	private void handleResult(String pagePath, PageVerificationResult result) {
		for(PageVerificationResultHandler handler : m_pageResultHandlers) {
			handler.handleResult(pagePath, result);
		}
	}
	
	private List<Table> getTemplates(TableTemplateLoader templateLoader) {
		LinkedList<Table> templates = new LinkedList<Table>();
		TableElementParser parser = new TableElementParser();

		for (Class<?> clazz : templateLoader.getFixtureClasses().values()) {
			Vector<String> rawTable = templateLoader.getTemplate(clazz.getName());
			Table template = parser.parseTable(rawTable);
			if (template.getData().size() > 0) {
				templates.add(template);
			}
		}

		return templates;
	}
}
